/**
	License:		Artistic license 2.0 (see license.txt, also available online at http://www.perlfoundation.org/artistic_license_2_0)
	Authors:		OrbitalLab (http://www.orbitallab.ru/moonglide/), 2007-2009

	File:			UploadManager.d
	Description:	upload manager, for register resources uploading
	Date:			10.01.2008 by Jurec
*/
module moonglide.core.UploadManager;

import
	moonglide.core.EngineCore,
	moonglide.renderer.IRendererRes,
	moonglide.resources.Management;


class CUploadManager : IEventListener
{
	mixin TMoonGlideObject;

	protected:
		IResource[char[]]	_loadToResList;		//	list of res with "loading" state
		IResource[char[]]	_loadList;			//	list of res with "loaded" state

		void XUnloadRes( IResource res )
		{
			switch( res.LoadState )
			{
				case EResLoadState.notloaded:
					debug debugLog.trace( "Trying to unload res with \"not loaded\" state");
					break;

				case EResLoadState.loading:
					_loadToResList.remove( res.id );
					res.setNotLoaded;
					break;

				case EResLoadState.loaded:
					CEngineCore().renderer.resLoader.unLoadRes( res );
					_loadList.remove( res.id );
					break;

				default:
					moonAssert( 0, "default switch in XUnloadRes called!", __FILE__, __LINE__ );
					break;
			}
		}

		void XUploadRes( IResource res )
		{
			switch( res.LoadState )
			{
				case EResLoadState.notloaded:
					char[] iid = res.id;
					//res.setLoading()
					_loadToResList[ iid ] = res;
					break;

				case EResLoadState.loading:
					// // NOTE (Jura#1#): set res priority to an upper level?
					break;

				case EResLoadState.loaded:
					debug debugLog.trace( "Trying to load res with \"loaded\" state" );
					return;

				default:
					moonAssert( 0, "default switch in XUploadRes called!", __FILE__, __LINE__ );
					return;
			}

			update;
		}


		this(/*IRendererRes ResLoad*/)
		{
			_id = "UploadManager";
		}

		static CUploadManager singleton;

	public:
		static CUploadManager opCall()
		{
			if( singleton is null )
				singleton = new CUploadManager;

			return singleton;
		}


		int maxloadSize = 0, loadSize;

		void update()
		{
			if( _loadToResList.length == 0)
				return;

			int loadSize = 0;

			foreach( inout res; _loadToResList )
			{
				debug
				{
					if( !res )
					{
						errorLog( "Upload manager: res from _loadToResList is null!" );
						continue;
					}
					else
						debug debugLog.trace( "Upload: " ~ res.id );
				}

				CEngineCore().renderer.resLoader.upLoadRes( res );

				_loadList[ res.id ] = res;

				if( maxloadSize != 0 )
				{
					loadSize += res.getSize();

					//	if we reached max load size by update() call
					if( loadSize >= maxloadSize )
						break;
				}
			}

			_loadToResList = null;

			debug
			{
				debugLog.trace( "_loadList:" );

				foreach( inout res; _loadList )
					debugLog.trace( res.id );

				debugLog.trace( "LoadingList:" );

				foreach ( inout res; _loadToResList )
					debugLog.trace( res.id );
			}

		}


		void UnloadAll_CleanLists()
		{
			foreach( inout res; _loadToResList )
			{
				res.setNotLoaded();
			}

			_loadToResList = null;

			foreach( inout res; _loadList )
			{
				CEngineCore().renderer.resLoader.unLoadRes( res );
				res.setNotLoaded();
			}

			_loadList = null;
		}


		void UnloadAll_KeepLists()
		{
			foreach( inout res; _loadList )
				CEngineCore().renderer.resLoader.unLoadRes( res );
		}


		void ReloadAllFromLists()
		{
			foreach( inout res; _loadToResList )
				res.setLoading();

			foreach( inout res; _loadList )
			{
				res.setNotLoaded();
				CEngineCore().renderer.resLoader.upLoadRes( res );
				res.setLoaded();
			}
		}


		void onEventCallback( CEvent event, IEventGenerator gen )
		{
			switch( event.type )
			{
				case eeventtype.resource:
					switch( event.subtype )
					{
						case eresourceevent.created:
							break;

						case eresourceevent.destroyed:
							if( cast(IResource)gen !is null )
								XUnloadRes( cast(IResource)gen );
							break;

						case eresourceevent.load:
							if( cast(IResource)gen !is null )
								XUploadRes( cast(IResource)gen );
							break;

						case eresourceevent.unload:
							if( cast(IResource)gen )
								XUnloadRes( cast(IResource)gen );
							break;

						default: break;
					}
					break;

				default: break;
			}
		}


		void onEventReceive( CEvent event, IEventSender sender )
		{
			//
		}


		debug void DbgReport()
		{
		    debugLogY( "----------------" );
			debugLogY( "UploadManager. begin of report" );
			debugLogY( "File: <" ~ __FILE__ ~ ">" );
			debugLogY( "----------------" );

			debugLog.trace(" loadToResList:");

			foreach ( inout Res; _loadToResList )
				debugLog.trace("  " ~ Res.id );

			debugLog.trace(" loadList:");

			foreach ( inout Res; _loadList )
				debugLog.trace("  " ~ Res.id );

			debugLogY("UploadManager. end of report");
			debugLogY("----------------");
		}
}
